package com.example.dsl

import org.junit.Test


/**
 * DSL语言
 * 泛型协变和逆变
 *
 * // 协变：父类泛型引用接收子类的对象  ？ Extend == out (父类接收子类，合理，协作的)
 * List<? Extends Object>() list = List<String>()
 * // 逆变：子类泛型引用接收父类泛型引用的对象  ? Super == in (子类接收父类，不合理，逆向)
 * 总结：
 * // 如果我们只需要读取泛型数据（生产者），就可以把泛型声明成协变（? Extends T）KT out 协变 读取
 * // 如果我们只需要修改泛型数据（消费者），就可以把泛型声明成逆变（？super T）   KT in    逆变 修改
 * @author zhouronghua
 *
 * @time 2022/3/27 3:41 下午
 */
open class Person() {
    override fun toString(): String {
        return "Person()"
    }
}

open class Teacher : Person() {
    override fun toString(): String {
        return "Teacher..."
    }
}

class Dog {
    fun show() {
        println("Dog 显示方式")
    }

    fun show2(str: String) {
        println("show run Dog $str")
    }
}

// 采用泛型协变访问
fun <T : Person> myShow(item: T) {
    // 会自动调用item.toString()方法
    println(item)
}

// 采用Lambda的泛型
fun <T : () -> Unit> myShow2(item: T) {
    // 直接执行泛型函数
    item.invoke()
}

// 采用Lambda的泛型
fun <T : (String) -> Unit> myShow3(str: String, item: T) {
    // 直接执行泛型函数
    item.invoke(str)
}

class DSLTest03 {

    @Test
    fun testGeneric() {
        // 测试父类
        myShow(Person())
        // 调用子类
        myShow(Teacher())
        println("通过模板调用函数")
        myShow2(Dog()::show)
        myShow3("小猫" ) {
            println("狗哥哥特别喜欢逗 $it")
        }
    }
}